package com.itboyst.facedemo.util;

import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.Rect;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @version:
 * @author: x55admin ming1332236@126.com
 * @date: 2020/4/28 15:02.
 */
public class ImageUtil {
    /**
     * Mat转换成BufferedImage
     *
     * @param matrix        要转换的Mat
     * @param fileExtension 格式为 ".jpg", ".png", etc
     * @return
     */
    public static BufferedImage mat2BufImg(Mat matrix, String fileExtension) {
        // convert the matrix into a matrix of bytes appropriate for
        // this file extension
        MatOfByte mob = new MatOfByte();
        Imgcodecs.imencode(fileExtension, matrix, mob);
        // convert the "matrix of bytes" into a byte array
        byte[] byteArray = mob.toArray();
        BufferedImage bufImage = null;
        try {
            InputStream in = new ByteArrayInputStream(byteArray);
            bufImage = ImageIO.read(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufImage;
    }

    /**
     * BufferedImage转换成Mat
     *
     * @param original 要转换的BufferedImage
     * @param imgType  bufferedImage的类型 如 BufferedImage.TYPE_3BYTE_BGR
     * @param matType  转换成mat的type 如 CvType.CV_8UC3
     */
    public static Mat bufImg2Mat(BufferedImage original, int imgType, int matType) {
        if (original == null) {
            throw new IllegalArgumentException("original == null");
        }

        // Don't convert if it already has correct type
        if (original.getType() != imgType) {

            // Create a buffered image
            BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);

            // Draw the image onto the new buffer
            Graphics2D g = image.createGraphics();
            try {
                g.setComposite(AlphaComposite.Src);
                g.drawImage(original, 0, 0, null);
            } finally {
                g.dispose();
            }
        }

        DataBufferByte dbi = (DataBufferByte) original.getRaster().getDataBuffer();
        byte[] pixels = dbi.getData();
        Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
        mat.put(0, 0, pixels);
        return mat;
    }

    /**
     * 添加标记
     *
     * @param bufferedImage
     * @param videoFaceInfoList
     * @param name
     * @param score
     * @param rect
     * @return
     */
    public static Mat addMark(BufferedImage bufferedImage, List<FaceInfo> videoFaceInfoList, int faceId, String name, float score, Rect rect, int age, String gender, String liveness) {
        Mat frame;
        Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(bufferedImage, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), null);
        g.setColor(new Color(0, 255, 0, 255));
        g.setFont(new Font("04b_08", Font.PLAIN, 32));
        //设置水印的坐标
        int x1 = rect.left;
        int y1 = rect.top;
        //显示人脸标记
        g.drawString(name + " " + age + " " + gender + " " + liveness + " " + score, x1, y1);
        g.dispose();
        frame = ImageUtil.bufImg2Mat(bufferedImage, BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);
        //标记人脸
        List<RotatedRect> boxs = ShowVideo.boundingBox(videoFaceInfoList);
        ShowVideo.drawRotatedBox(frame, boxs, new Scalar(0, 255, 0));
        return frame;
    }

    public static Map<String, File> getImgInfo(String filesPath) {
        Map<String, File> imgInfoMap = new HashMap<String, File>();
        File file = new File(filesPath);
        File[] files = file.listFiles();
        for (File f : files != null ? files : new File[0]) {
            try {
                //读取图片转换为流
                FileInputStream fis = new FileInputStream(f);
                String name = "";
                String[] split = f.getName().split("\\.");
                if (split.length > 1) {
                    name = split[0];
                }
                String filePath = f.getPath();
                imgInfoMap.put(name, f);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return imgInfoMap;
    }

    public static byte[] inputStreamToBytes(InputStream ins) {
        byte[] data = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            int i = -1;
            byte[] buf = new byte[1024];
            while ((i = ins.read(buf)) != -1) {
                baos.write(buf, 0, i);
            }
            data = baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    /**
     * 图片截取
     *
     * @param bufferedImage
     * @param x
     * @param y
     * @param w
     * @param h
     * @return
     * @throws IOException
     */
    public static BufferedImage cropImage(BufferedImage bufferedImage, int x, int y, int w, int h) throws IOException {
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        //避免抛出java.awt.image.RasterFormatException
        if (width > x + w && height > y + h && x > 0 && y > 0) {
            bufferedImage = bufferedImage.getSubimage(x, y, w, h);
        }
        return bufferedImage;
    }

    /**
     * 调整bufferedimage大小
     *
     * @param source  BufferedImage 原始image
     * @param targetW int  目标宽
     * @param targetH int  目标高
     * @param flag    boolean 是否同比例调整
     * @return BufferedImage  返回新image
     */
    public static BufferedImage resizeBufferedImage(BufferedImage source, int targetW, int targetH, boolean flag) {
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        if (flag && sx > sy) {
            sx = sy;
            targetW = (int) (sx * source.getWidth());
        } else if (flag && sx <= sy) {
            sy = sx;
            targetH = (int) (sy * source.getHeight());
        }
        if (type == BufferedImage.TYPE_CUSTOM) { // handmade
            ColorModel cm = source.getColorModel();
            WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
            boolean alphaPremultiplied = cm.isAlphaPremultiplied();
            target = new BufferedImage(cm, raster, alphaPremultiplied, null);
        } else {
            target = new BufferedImage(targetW, targetH, type);
        }
        Graphics2D g = target.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }
}
